package com.adtech.adms.system.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import com.adtech.adms.commons.ErrorCode;
import com.adtech.adms.commons.web.listener.OnlineUserListener;
import com.adtech.adms.system.SystemConstants;
import com.adtech.adms.system.pojo.Role;
import com.adtech.adms.system.pojo.Topo;
import com.adtech.adms.system.pojo.User;
import com.adtech.adms.system.service.FeatureService;
import com.adtech.adms.system.service.UserService;
import com.adtech.core.Settings;
import com.adtech.core.cache.Cache;
import com.adtech.core.dao.HibernateDAO;
import com.adtech.core.dao.exp.Expression;
import com.adtech.core.dao.query.Pager;
import com.adtech.core.dao.query.QueryConstants;
import com.adtech.core.dao.query.QueryCriterions;
import com.adtech.core.dao.query.Sort;
import com.adtech.core.exception.ServiceException;
import com.adtech.core.util.MD5Util;
import com.adtech.core.util.StringUtil;

/**
 * 用户service实现类
 * 实现用户模块业务操作
 * @author Dormin 
 * @since 2011-8-11 
 * 
 * @Copyright (C) AD Tech Workshop All Right Reserved
 */
public class UserServiceImpl implements UserService {
	
	private static final String LOGIN_SINGLE = "login.single";

	private HibernateDAO dao;

	private Cache templateCache;
	private FeatureService featureService;
	

	public Cache getTemplateCache() {
		return templateCache;
	}

	public void setTemplateCache(Cache templateCache) {
		this.templateCache = templateCache;
	}


	public FeatureService getFeatureService() {
		return featureService;
	}

	public void setFeatureService(FeatureService featureService) {
		this.featureService = featureService;
	}

	public User login(String userName, String password,String ip,String newSessionId,String reason) throws ServiceException {
		QueryCriterions hc = new QueryCriterions();
		hc.and(SystemConstants.User.LOGIN_NAME, userName, QueryConstants.EQ);
		User user = null;
		List<User> userList = (List<User>) dao.getByQuery(User.class, hc.toExpression());
		if(userList.size()>0) {
			user = userList.get(0);
		}
		if (user == null) {
			throw new ServiceException(ErrorCode.USER_NOT_EXIST);
		}			
		/*
		if (!MD5Util.md5(password).equals(user.getPassword())) {
			throw new ServiceException(ErrorCode.USER_PWD_NOT_MATCH);
		}
		*/
		// Dormin安评修改
//		if (!password.equals(user.getPassword())) {
//			throw new ServiceException(ErrorCode.USER_PWD_NOT_MATCH);
//		}
		
		checkLoginType(user);
		
		String oldSessionId = user.getSessionId();
		if(oldSessionId != null && !oldSessionId.equals(newSessionId)) {
			// 当同一用户再次登录时，暂时先不踢出前一登录用户
			if(Settings.getBoolean(LOGIN_SINGLE)){
				OnlineUserListener.invalidSession(oldSessionId,reason);
			}
		}
		
		user.setSessionId(newSessionId);
		user.setLastLoginTime(new Date());
		dao.saveOrUpdate(user);
		
		
		user.setLoginIp(ip);
		user.setFeaturesTree(featureService.getFeatureListByUser(user));
	//	systemLogService.addLog(LogConstants.LOG_TYPE_USER_LOGIN,new Object[]{user.getLoginName()},user);
	//	systemLogService.saveLoginLog(user);
		return user;
	}
	
	public User getUser(int id) {
		User user = dao.getById(User.class, id);
//		List<Role> roles = user.getRoles();
//		for (Role role : roles) {
//			dao.initialize(role);
//		}
		return user;
	}

	public List<User> getUserList(Pager pager, Expression expression, Sort sort) {
		if(sort==null || sort.isEmpty()) {
			sort = new Sort();
			sort.addSort(SystemConstants.User.LAST_LOGIN_TIME, QueryConstants.DESC);
		}
		//expression = Condition.and(Condition.eq(SystemConstants.User.IS_DELETE, "0"), expression);
		return (List<User>)dao.getByQuery(User.class, pager, expression, sort);
	}

	public void save(User newUser,User currentUser) throws ServiceException {
		if (newUser.getUserId() == null) {
			User user=new User();
			mergeUser(user,newUser);
			user.setCreateTime(new Date());
			user.setEditTime(new Date());
			dao.add(user);			
		} else {
			User user = (User)dao.loadById(User.class, newUser.getUserId());
			mergeUser(user,newUser);
			user.setEditTime(new Date());
			dao.saveOrUpdate(user);
			templateCache.remove(user.getUserId());
		}
	}

	private void mergeUser(User user, User newUser) {
		if(user.getUserId() != null){
			user.setRoles(null);
			dao.saveOrUpdate(user);
		}
		
		List<Role> roles = new ArrayList<Role>();
		for (Role role : newUser.getRoles()) {
			roles.add(dao.getById(Role.class, role.getRoleId()));
		}
		user.setRoles(roles);
		
		List<Topo> topos = new ArrayList<Topo>();
		for (Topo topo : newUser.getTopos()) {
			topos.add(dao.getById(Topo.class, topo.getId()));
		}
		user.setTopos(topos);
		
		user.setUserName(newUser.getUserName());
		if(!StringUtil.isEmpty(newUser.getPassword())){
			user.setPassword(MD5Util.md5(newUser.getPassword()));
		}
		user.setLoginName(newUser.getLoginName());
		user.setLoginType(newUser.getLoginType());
		user.setEmail(newUser.getEmail());
		user.setMobile(newUser.getMobile());
		user.setPhone(newUser.getPhone());
		if(newUser.getSessionId()!=null){
			user.setSessionId(newUser.getSessionId());
		}
	}

	public void delete(String id,User currentUser) {
		if (id == null || id.length() == 0) {
			return;
		}
		String[] ids = id.split(",");
		for(String userId : ids) {
			if(userId!=null && userId.length()>0) {
				User user = dao.getById(User.class, Integer.parseInt(userId));
				dao.delete(user);
//				user.setIsDelete("1");
//				dao.saveOrUpdate(user);
			}
		}
		dao.flushSession();
	}

	public void check(User user) throws ServiceException {
		if(user==null){
			throw new ServiceException(ErrorCode.USER_NOT_EXIST);
		}
		else{
			QueryCriterions hc = new QueryCriterions();
			hc.and(SystemConstants.User.LOGIN_NAME, user.getLoginName(), QueryConstants.EQ);
//			hc.and(SystemConstants.User.IS_DELETE, "0", QueryConstants.EQ);
			hc.and(SystemConstants.User.USER_ID, user.getUserId(), QueryConstants.NE);
			User oldUser = dao.getOneByQuery(User.class, hc.toExpression());
			if (oldUser != null) {
				throw new ServiceException(ErrorCode.USER_LOGIN_NAME_DUPLICATE);
			}
		}
	}

	public void changePassword(User user,String password,String newPassword,User currentUser) throws ServiceException {
		User oldUser = (User)dao.loadById(User.class, user.getUserId());
		if (oldUser == null) {
			throw new ServiceException(ErrorCode.USER_NOT_EXIST);
		}
		if(!MD5Util.md5(password).equals(oldUser.getPassword())){
			throw new ServiceException(ErrorCode.USER_PWD_NOT_MATCH);
		}
		//oldUser.setPassword(newPassword);
		oldUser.setPassword(MD5Util.md5(newPassword));
		dao.saveOrUpdate(oldUser);
	}

	public String resetPassword(String id) throws ServiceException {
		User user = (User)dao.loadById(User.class, Long.parseLong(id));
		if (user == null) {
			throw new ServiceException(ErrorCode.USER_NOT_EXIST);
		}
		String password = generateRandomPassword();
		user.setPassword(MD5Util.md5(password));
		dao.saveOrUpdate(user);
		return password;
	}

	/**
	 * 
	 * @function 随机生成6位密码（目前仅数字）
	 * @param
	 *
	 * @return
	 * @exception
	 *
	 * @author Dormin
	 * @history
	 *
	 */
	public static String generateRandomPassword(){
		StringBuilder builder = new StringBuilder();
		Random random = new Random();
		for(int i=0;i<4;i++){
			builder.append(Math.abs(random.nextInt())%10);
			char c='a';
			c=(char)(c+(int)(Math.random()*26));
			builder.append(c);
		}
		return builder.toString();
	}

	public void checkLoginType(User user) throws ServiceException {
		if(user!=null && user.getLoginType()!=null && user.getLoginType().byteValue()!=0){
			if((user.getLoginType().byteValue() & User.TYPE_SYSTEM) != User.TYPE_SYSTEM){
				// VPN用户，需要检查登录ip是否合法的VPN服务器
				if((user.getLoginType().byteValue() & User.TYPE_VPN) == User.TYPE_VPN){
					if(!checkVPNServer(user.getLoginIp())){
						throw new ServiceException(ErrorCode.USER_NOT_ALLOWED);
					}
				}
				//EIP或其他用户，不允许从此处登录
				else{
					throw new ServiceException(ErrorCode.USER_NOT_ALLOWED);
				}
			}
		}
	}

	/**
	 * 
	 * @function 检查IP地址是否是合法的VPN服务器
	 * @param ip 用户登录的ip地址
	 *
	 * @return 验证结果，合法返回true，否则返回false
	 * @exception
	 *
	 * @author
	 * @history
	 *
	 */
	private boolean checkVPNServer(String ip) {
		// TODO 将用户登录ip地址与设置的合法VPN服务器ip地址进行比较
		return true;
	}

	public void checkPassword(Integer userId, String password)
	throws ServiceException {
		User user = (User)dao.loadById(User.class, userId);
		if (user == null) {
			throw new ServiceException(ErrorCode.USER_NOT_EXIST);
		}
		if(!MD5Util.md5(password).equals(user.getPassword())){
			throw new ServiceException(ErrorCode.USER_PWD_NOT_MATCH);
		}
	}

	public void update(User user) {
		dao.saveOrUpdate(user);
	}

	public void setDao(HibernateDAO dao) {
		this.dao = dao;
	}


}
